package alocador.util;

import java.util.Calendar;
import java.util.GregorianCalendar;
import alocador.exceptions.DataInvalidaException;

/**
 * Classe auxiliar que verifica entradas invalidas
 */
public class VerificaInvalido {
	
	private final static int PRIMEIRO_DIA_MES = 1;
	private final static int ULTIMO_DIA_MES = 31;
	private final static int PENULTIMO_DIA_MES = 30;
	private final static int FEVEREIRO_BISSEXTO = 29;
	private final static int ULTIMO_DIA_MES_FEVEREIRO = 28;
	
	/**
	 * Metodo que verifica se uma data vem depois da data atual
	 * @param data
	 *      A data a ser verificada
	 * @return 
	 * 		True, se a data analisada vier depois da data atual. False, caso contrario
	 * @throws DataInvalidaException
	 * 		Verifica se a data e invalida, 30/02, por exemplo
	 */
	public static boolean dataInvalida(GregorianCalendar dataInicio,
			GregorianCalendar dataFim) throws DataInvalidaException {

		if ((dataCorreta(dataInicio) && dataCorreta(dataFim))){
			if (dataInicio.compareTo(dataFim) > 0) {
				return true;
			}
		}
		
		//Verifica se a data ja passou
		GregorianCalendar hoje = new GregorianCalendar();
		if (dataInicio.before(hoje) || dataFim.before(hoje))
			return true;
		
		
		// Verifica se os eventos estão no mesmo dia
		if (dataInicio.get(Calendar.DAY_OF_YEAR) == dataFim.get(Calendar.DAY_OF_YEAR))
			return false;
		

		return true;
	}

	
	/**
	 * Verifica se uma data esta correta
	 * @param data
	 * 		Data a ser verificada
	 * @return
	 * 		True, se a data estiver no formato correto. False, caso contrario
	 * @throws DataInvalidaException
	 * 		Verifica se a data e invalida, 30/02, por exemplo
	 */
	private static boolean dataCorreta(GregorianCalendar data)
			throws DataInvalidaException {
		
		int dia = data.get(GregorianCalendar.DAY_OF_MONTH);
		int mes = data.get(GregorianCalendar.MONTH);
		int ano = data.get(GregorianCalendar.YEAR);
		
		if (mes == Calendar.APRIL || mes == Calendar.JUNE || mes == Calendar.SEPTEMBER || mes == Calendar.NOVEMBER) {
			if (dia < PRIMEIRO_DIA_MES || dia > PENULTIMO_DIA_MES) {
				return false; // meses com 30 dias
			}
		
		} else if ( data.isLeapYear(ano) ) {
			if (mes == Calendar.FEBRUARY){
				if (dia < PRIMEIRO_DIA_MES || dia > FEVEREIRO_BISSEXTO ) {
					return false; // Fevereiro com 29 dias
				}
			}
		} else if (mes == Calendar.FEBRUARY) {
			if (dia < PRIMEIRO_DIA_MES || dia > ULTIMO_DIA_MES_FEVEREIRO) {
				return false; // Fevereiro com 28 dias
			}
		} else {
			if (dia < PRIMEIRO_DIA_MES || dia > ULTIMO_DIA_MES) {
				return false; // meses com 31 dias
			}
		}
		return true;
	}

	/**
	 * Metodo responsavel por verificacao basica
	 * @param texto
	 *      Representa a string a ser analisada
	 * @return 
	 * 		True, se a string for null, vazia ou em branco. False, caso contrario
	 */
	public static boolean basico(String texto) {

		if ((texto == null) || (texto.replace(" ", "").equals("")))
			return true;

		return false;
	}

	/**
	 * Metodo responsavel por verificar se o nome tem formatacao invalida
	 * @param texto
	 * 		Representa o nome a ser analisado
	 * @return 
	 * 		True, se passar no teste basico e conter apenas letras. False, caso contrario
	 */
	public static boolean nome(String texto) {

		if (basico(texto))
			return true;

		texto = texto.replace(" ", "");
		for (int i = 0; i < texto.length(); i++) {
			if (!(Character.isLetter(texto.charAt(i))))
				return true;
		}

		if (Character.isTitleCase(texto.charAt(0)))
			return true;

		return false;
	}

	/**
	 * Metodo responsavel por verificar se o numero tem formatacao invalida
	 * @param numero
	 *            Representa o numero a ser analisado
	 * @return True, se passar no teste basico e conter apenas numeros <br>
	 *         False, caso contrario
	 */
	public static boolean numero(String numero) {

		if (basico(numero))
			return true;

		for (int i = 0; i < numero.length(); i++) {
			if (!(Character.isDigit(numero.charAt(i))))
				return true;
		}
		return false;
	}
	
	
	/**
	 * Verifica se um evento cai num Sabado ou Domingo
	 * @param data
	 * 		Data do Evento
	 * @return
	 * 		True, se cair em um Final de Semana. False, caso contrario
	 */
	public static boolean ehFinalDeSemana(String data){
		String split[] = data.trim().split(" ");
		
		String date = split[0];

		String dataCompleta[] = date.trim().split("/");
		int dia = Integer.parseInt(dataCompleta[0]);
		int mes = Integer.parseInt(dataCompleta[1]);
		int ano = Integer.parseInt(dataCompleta[2]);
		
		GregorianCalendar gc = new GregorianCalendar(ano, mes-1, dia);
		
		if (gc.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY || gc.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY){
			return true;
		}
		
		return false;
	}
}
